package com.sun.lib_tag;

import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;

import java.util.ArrayList;
import java.util.List;

/*
 *
 * #                                                   #
 * #                       _oo0oo_                     #
 * #                      o8888888o                    #
 * #                      88" . "88                    #
 * #                      (| -_- |)                    #
 * #                      0\  =  /0                    #
 * #                    ___/`---'\___                  #
 * #                  .' \\|     |# '.                 #
 * #                 / \\|||  :  |||# \                #
 * #                / _||||| -:- |||||- \              #
 * #               |   | \\\  -  #/ |   |              #
 * #               | \_|  ''\---/''  |_/ |             #
 * #               \  .-\__  '-'  ___/-. /             #
 * #             ___'. .'  /--.--\  `. .'___           #
 * #          ."" '<  `.___\_<|>_/___.' >' "".         #
 * #         | | :  `- \`.;`\ _ /`;.`/ - ` : | |       #
 * #         \  \ `_.   \_ __\ /__ _/   .-` /  /       #
 * #     =====`-.____`.___ \_____/___.-`___.-'=====    #
 * #                       `=---='                     #
 * #     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~   #
 * #                                                   #
 * #               佛祖保佑         永无BUG              #
 * #                                                   #
 */

/**
 * Created by ESSC07 on 2021/12/13.
 */
public abstract class TagFlowGroup extends ViewGroup {
    private int mGravity; // 对齐方式，默认局左对齐

    private int horizontalSpace = 0;    // 水平方向间距
    private int verticalSpace = 0;      // 垂直方向间距
    private List<Integer> numberList = new ArrayList<>(); // 每行显示个数
    private List<Integer> lineWidthList = new ArrayList<>(); // 每行view的左边距和的集合
    private List<Integer> lineHeightList = new ArrayList<>(); //

    private List<List<View>> views = new ArrayList<>();


    public TagFlowGroup(Context context) {
        this(context, null);
    }

    public TagFlowGroup(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public TagFlowGroup(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.TagFlowGroup);
        mGravity = array.getInt(R.styleable.TagFlowGroup_orientation, TagMode.LEFT);
        horizontalSpace = array.getDimensionPixelOffset(R.styleable.TagFlowGroup_horizontalSpace, dp2px(2));
        verticalSpace = array.getDimensionPixelSize(R.styleable.TagFlowGroup_verticalSpace, dp2px(2));
        array.recycle();
    }

    /**
     * 设置布局方向
     *
     * @param mGravity
     */
    public void setGravity(@TagOri int mGravity) {
        this.mGravity = mGravity;
        notifyAdapter();
    }

    protected abstract void notifyAdapter();

    // 通过计算tagview的宽高，确定画布的宽高度
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        // super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);

        int width = 0; // 控件总宽度
        int height = 0; // 控件总高度

        int lineWidth = 0; // 每行总宽度
        int lineHeight = 0; // 每行高度

        int lineCounter = 0; // 每行个数计数

        for (int i = 0; i < getChildCount(); i++) {
            View child = getChildAt(i);
            if (child.getVisibility() == GONE) {
                if (i == getChildCount() - 1) {
                    width = Math.max(lineWidth, width);
                    height += lineHeight;
                }
                continue;
            }
            measureChild(child, widthMeasureSpec, heightMeasureSpec);
            MarginLayoutParams params = null;
            LayoutParams layoutParams = child.getLayoutParams();
            if (layoutParams instanceof MarginLayoutParams)
                params = (MarginLayoutParams) layoutParams;
            else
                params = new MarginLayoutParams(layoutParams.width, layoutParams.height);

            int childWidth = child.getMeasuredWidth() + params.leftMargin + params.rightMargin;
            int childHeight = child.getMeasuredHeight() + params.topMargin + params.bottomMargin;
            /*if (numberList.size() == 0) {
                if (lineWidth + childWidth > widthSize - getPaddingLeft() - getPaddingRight()) {
                    width = Math.max(lineWidth, width);
                    lineWidth = childWidth;
                    height += lineHeight + verticalSpace;
                    lineHeight = childHeight;
                } else {
                    lineWidth += childWidth;
                    lineHeight = Math.max(lineHeight, childHeight);
                }
            } else {
                lineCounter++;
            }*/
            int realWidthSize = widthSize - getPaddingLeft() - getPaddingRight();
            if (lineWidth + childWidth > realWidthSize) {
                width = Math.max(lineWidth, width);
                lineWidth = childWidth;
                height += lineHeight + verticalSpace;
                lineHeight = childHeight;
            } else {
                if (lineWidth + childWidth + horizontalSpace > realWidthSize) {
                    lineWidth = realWidthSize;
                } else {
                    lineWidth += childWidth;
                }
                lineHeight = Math.max(lineHeight, childHeight);
            }

            if (i == getChildCount() - 1) {
                width = Math.max(lineWidth, width);
                height += lineHeight;
            }
        }

        setMeasuredDimension(widthMode == MeasureSpec.EXACTLY ? widthSize : width + getPaddingLeft() + getPaddingRight(),
                heightMode == MeasureSpec.EXACTLY ? heightSize : height + getPaddingTop() + getPaddingBottom());
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        lineWidthList.clear();
        lineHeightList.clear();
        views.clear();
        List<View> lineViews = new ArrayList<>();

        int lineWidth = 0;
        int lineHeight = 0;
        int width = getWidth();
        for (int i = 0; i < getChildCount(); i++) {
            View child = getChildAt(i);
            if (child.getVisibility() == GONE) continue;
            MarginLayoutParams params = (MarginLayoutParams) child.getLayoutParams();
            int childWidth = child.getMeasuredWidth();
            int childHeight = child.getMeasuredHeight();
            if (lineWidth + childWidth + horizontalSpace > width - getPaddingLeft() - getPaddingRight()) {
                /*// 可以正常放下时，将当前view的左边距添加到list中
                leftList.add(lineWidth + getPaddingLeft());
                lineWidth += childWidth + horizontalSpace;
                lineViews.add(child);*/
                if (!lineViews.isEmpty()) {
                    lineWidthList.add(lineWidth);
                    lineHeightList.add(lineHeight);
                    views.add(lineViews);
                    lineViews = new ArrayList<>();
                    lineWidth = 0;
                    lineHeight = 0;
                }

            }
            lineWidth += childWidth + horizontalSpace;
            lineHeight = Math.max(lineHeight, childHeight + params.topMargin + params.bottomMargin + horizontalSpace);
            lineViews.add(child);
        }
        lineWidthList.add(lineWidth);
        lineHeightList.add(lineHeight);
        views.add(lineViews);

        int left = getPaddingLeft();
        int top = getPaddingTop();
        for (int i = 0; i < views.size(); i++) {
            lineViews = views.get(i);
            lineHeight = lineHeightList.get(i);
            lineWidth = lineWidthList.get(i);
            int averageSpace = horizontalSpace;
            switch (mGravity) {
                case TagMode.LEFT:
                    left = getPaddingLeft();
                    break;
                case TagMode.RIGHT:
                    left = width - lineWidth + getPaddingLeft() + averageSpace;
                    break;
                case TagMode.CENTER:
                    left = (width - lineWidth) / 2 + getPaddingLeft();
                    break;
                case TagMode.FILL:
                    left = getPaddingLeft();
                    averageSpace += (width - lineWidth + averageSpace) / (lineViews.size() - 1);
                    break;
            }
            for (int j = 0; j < lineViews.size(); j++) {
                View child = lineViews.get(j);
                if (child.getVisibility() == GONE) {
                    continue;
                }
                MarginLayoutParams params = (MarginLayoutParams) child.getLayoutParams();
                int childLeft = left + params.leftMargin;
                int childTop = top + params.topMargin;
                int childRight = childLeft + child.getMeasuredWidth();
                int childBottom = childTop + child.getMeasuredHeight();
                child.layout(childLeft, childTop, childRight, childBottom);

                left += averageSpace + child.getMeasuredWidth();
            }
            top += lineHeight;

        }
    }

    @Override
    public LayoutParams generateLayoutParams(AttributeSet attrs) {
        return new MarginLayoutParams(getContext(), attrs);
    }

    @Override
    protected LayoutParams generateLayoutParams(LayoutParams p) {
        return new MarginLayoutParams(p);
    }

    @Override
    protected LayoutParams generateDefaultLayoutParams() {
        return new MarginLayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
    }

    public int dp2px(int dp) {
        final float scale = getContext().getResources().getDisplayMetrics().density;
        return (int) (dp * scale + 0.5f);
    }

    public static class TagMode {
        public static final int LEFT = 0;
        public static final int RIGHT = 1;
        public static final int CENTER = 2;
        public static final int FILL = 3;
    }
}
